树与二叉树——数据结构系列教程(c++版)

梦想不会自己发光,真正闪耀的是那个为梦狂奔的你。献给知行的孩子们!(Eric.He著)


  在数据结构的世界中,我们已经接触过线性结构(如数组、链表、栈、队列),它们的特点是数据元素之间呈“一对一”的线性关系。但在实际生活中,很多场景的关系并非线性,比如:

  这些“一对多”的层级关系,用线性结构难以高效表示和处理,而“树”结构正是为解决这类问题而生的。树结构不仅能清晰地刻画层级关系,还能提供高效的查找、插入、删除操作,是后续学习红黑树、B树、堆等高级数据结构的基础。

  二叉树是树结构中最常用、最核心的一种,它的结构相对简单,且任何复杂的树都可以转化为二叉树来处理,因此本教程将重点围绕树的基本概念和二叉树展开。

教程目录导航

一、树的基本概念与定义

1.1 树的定义

树(Tree)是由n(n≥0)个有限节点组成的具有 层次关系 的集合,当n=0时,称为“空树”;当n≥1时,树的结构满足以下两个条件:

  1. 有且仅有一个特定的节点,称为根节点(Root),它没有前驱节点;
  2. 其余的节点可以分为m(m≥0)个互不相交的有限集合T₁、T₂、…、Tₘ,每个集合本身又是一棵树,称为根节点的子树(Subtree)

1.2 关键概念

术语 定义
节点 节点(Node)是构成树的最基本、最核心的单元,所有树的操作(如插入、删除、遍历、查找)都是围绕节点展开的。二叉树的节点是存储数据 + 关联左右子节点 的数据单元,本质是 “数据 + 指针”。二叉树中通常包含根节点(root)、父节点(parent)、子节点(child)、左节点(left child)、右节点(right child)、叶节点(leaf)等称呼。
度(Degree) 是描述节点“分支能力” 的核心指标,一个节点拥有的子节点的数量(即该节点的 “分支数”)。例:二叉树的度为<=2、三叉树的度为<=3。
层次 层次(Level) 是描述节点在树中纵向位置的核心指标,用于衡量节点与根节点的 “距离”。
深度 深度(Depth)是从根节点到该节点的路径上的节点数(等价于层次数)
高度 高度(Height)从该节点到其最远叶子节点的路径上的节点总数。
路径 路径(Path)从一个节点到另一个节点的有序节点序列。

二、二叉树的定义与性质

2.1 二叉树的定义

二叉树(Binary Tree)是一种特殊的树结构,它的每个节点的度都不超过2,即每个节点最多有两个子树,且这两个子树有明确的左右之分,分别称为“左子树”和“右子树”。

2.2 二叉树的基本形态

二叉树有5种基本形态:

  1. 空二叉树(n=0);
  2. 只有根节点(n=1);
  3. 根节点只有左子树;
  4. 根节点只有右子树;
  5. 根节点既有左子树又有右子树。

2.3 二叉树的重要性质

二叉树具有以下几个核心性质,这些性质是后续学习二叉树遍历、存储和应用的基础:

2.4 三种特殊的二叉树

在二叉树中,有三种特殊的类型应用广泛:满二叉树、完全二叉树和平衡二叉树。

对比维度 满二叉树 完全二叉树 平衡二叉树
核心定义
  1. 所有非叶子节点都有两个子节点
  2. 所有叶子节点都在同一层
  1. 按层序编号(从上到下、从左到右),节点编号与相同高度的满二叉树完全对应
  2. 缺失的节点只能在最底层的右侧
任意节点的左右子树高度差的绝对值 ≤ 1(平衡因子 ∈ {-1,0,1})
节点数公式 高度为 h 时,总节点数 n=2h−1(节点数固定) 高度为 h 时,节点数范围 2h−1≤n≤2h−1 无固定公式,满足 h=O(log n) 即可
叶子节点特征 全部位于最底层,数量为 2h−1 叶子节点只能在最后两层,且最后一层的叶子靠左排列 叶子节点位置无限制,只需满足高度差约束
高度特性 高度 h=log2​(n+1),形态唯一 高度 h=⌊log2n⌋+1,形态不唯一 最大高度为 O(log n),避免退化为链表
包含关系
  1. 满二叉树 一定是 完全二叉树
  2. 满二叉树 一定是 平衡二叉树
  1. 完全二叉树 不一定是 满二叉树
  2. 完全二叉树 一定是 平衡二叉树
  1. 平衡二叉树 不一定是 完全 / 满二叉树
  2. 满 / 完全二叉树是平衡二叉树的特例
核心目标 结构极致规整,充分利用层级空间 适配数组存储(可通过下标直接定位父 / 子节点) 保证增删查的时间复杂度稳定在 O(log n),避免树退化为链表
判断方法
  1. 计算高度 h 和节点数 n,验证 n=2h−1
  2. 递归验证每个非叶子节点都有两个子节点,且叶子在同一层
按层序遍历,检查缺失节点是否都在最底层右侧
  1. 自顶向下:计算每个节点的左右子树高度差
  2. 自底向上:后序遍历,计算高度的同时判断平衡
常见应用 霍夫曼树、完美二叉树模型分析 堆(大顶堆 / 小顶堆)的底层存储结构、二叉树的数组化表示 平衡二叉搜索树(AVL 树、红黑树)、数据库索引、有序集合容器

2.5 遍历操作

遍历(Traversal) 指的是按照某种既定规则,依次访问树中所有节点且每个节点仅被访问一次的操作。所有树的操作(如插入、删除、遍历、查找)都需通过遍历算法实现。

二叉树每个节点包含根节点(N)左子树(L)右子树(R)三部分,遍历的核心是确定这三者的访问顺序。

四种遍历访问顺序

  1. 前序遍历:根 → 左 → 右
  2. 中序遍历:左 → 根 → 右
  3. 后序遍历:左 → 右 → 根
  4. 层序遍历:从上到下、从左到右

主流遍历方式分为深度优先遍历(DFS)广度优先遍历(BFS)两大类:

  1. 深度优先遍历(DFS):沿着一条路径尽可能深地访问节点,直到路径末端(叶子节点),再回溯到上一个节点,继续访问其他分支路径。
    1. 递归采用递推+回归方式天然支持DFS回溯思路,如果数据量大递归深度也就大,容易出现栈内存溢出。
    2. 迭代+栈也支持DFS回溯思路。下文第四节会具体讲解递归和迭代的方式实现遍历。
    3. 小数据量的前序、中序、后序遍历一般采用递归方式实现深度优先遍历(DFS),大数量的前序、中序、后序遍历采用迭代+栈实现深度优先遍历(DFS)。
  2. 广度优先遍历(BFS):按照节点的层次,从上到下、从左到右依次访问每一层的节点,也叫层次遍历。广度优先遍历(BFS)合适采用迭代+队列实现。
遍历方式 访问顺序 核心特性
(DFS)前序遍历 根 → 左 → 右 根节点优先访问,适合复制树结构
(DFS)中序遍历 左 → 根 → 右 对二叉搜索树(BST),输出升序序列
(DFS)后序遍历 左 → 右 → 根 子节点优先访问,适合删除树、计算子树大小
(BFS)层次遍历 从上到下、从左到右 能直观反映树的层级结构,适合计算树的高度、按层处理节点。

2.6 存储结构

二叉搜索树结构是一对多的关系,除了树根之外,每一个节点有唯一的直接前驱(父亲),除了叶子之外,每一个节点有一个或两个直接后继(孩子)。

可以采用顺序存储和链式存储两种形式:

(1)顺序存储(数组)

把根节点存储在下标 i = 1 的位置,把左子节点存储在下标 2 * i = 2 的位置,右子节点存储在 2 * i + 1 = 3 的位置。树为满二叉树完全二叉树时不会浪费太多存储空间。

(1)链式存储(结构体)

每一个节点有三个域,即数据域data、lchild左节点地址、rchild右节点地址。

2.7 核心操作

操作名称 功能描述
前序建立二叉树 根据前序和中序序列,建立一棵二叉树
后序建立二叉树 根据后序和中序序列,建立一棵二叉树
层序建立二叉树 根据层序和中序序列,建立一棵二叉树
删除二叉树 删除指定二叉树,包含它的左子树和右子树
前序遍历(递归) 根据根 → 左 → 右方式遍历打印二叉树所有元素
中序遍历(递归) 根据左 → 根 → 右方式遍历打印二叉树所有元素
后序遍历(递归) 根据左 → 右 → 根方式遍历打印二叉树所有元素
前序遍历(迭代) 根据根 → 左 → 右方式遍历打印二叉树所有元素
中序遍历(迭代) 根据左 → 根 → 右方式遍历打印二叉树所有元素
后序遍历(迭代) 根据左 → 右 → 根方式遍历打印二叉树所有元素
层序遍历(迭代) 从上到下、从左到右方式遍历打印二叉树所有元素

三、代码结构解析

3.1 整体架构

提供的代码是模板化的二叉树实现(支持任意类型),采用C++结构体封装,分为头文件(声明)和源文件(实现)两部分,核心结构如下:

模块 作用 关键结构/函数
二叉树结构体 封装所有操作 ArrayBinaryTree<T>(模板类)

3.2 关键结构体详解

(1)二叉树结构体(ArrayBinaryTree)

分为私有成员(内部实现)和公有成员(对外接口):

template <typename T>
struct ArrayBinaryTree{
    // ------------------------------------------------------------------------------------------------------
    //                                          私有成员
    // 注:私有成员只能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)不能访问调用)
    //------------------------------------------------------------------------------------------------------
    private:

        //---------------声明私有成员变量---------------

        T tree[MAXSIZE];   // 存储二叉树数据,支持任意类型
        int qty;         // 用于跟踪二叉树中的元素数量
        T valNull = T(); // 空节点标识(模板化)

        //---------------声明私有成员函数---------------
        //辅助函数
        int findRootIndex(const T inTree[], int start, int end, const T rootVal); // 查找根节点在中序序列中的索引
        int isInRange(const T val, const T inOrder[], int start, int end); // 检查元素是否在中序的指定范围内(用于筛选层序中的子树节点)
        int filterLevelNodes(const T levelOrder[], int levelLen, const T inOrder[], int inStart, int inEnd, T subLevel[]);// 筛选层序数组中属于指定中序范围的节点,生成子层序数组

    // ------------------------------------------------------------------------------------------------------
    //                                          公共成员
    // 注:公共成员能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)也能访问调用)
    //------------------------------------------------------------------------------------------------------
    public:

        //---------------声明公共成员函数---------------

        // 构造函数:外部通过该结构体定义(实例化)变量(对象)时,自动执行该函数(主要用于初始化成员变量的值)
        ArrayBinaryTree() {
            qty = 0;
            for(int i=0;i < MAXSIZE;i++) { tree[i] = T(); }
        }        

        //功能函数
        void buildTreeByPre(const T preTree[], int preStart, int preEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据前序和中序列建立二叉树
        void buildTreeByPost(const T postTree[], int postStart, int postEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据后序和中序列建立二叉树
        void buildTreeByLevel(const T levelTree[], int levelLen, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据层序和中序列建立二叉树
        void deleteTree(int index);// 删除二叉树

        //递归遍历
        void preOrder(int index);// 前序遍历(根 → 左 → 右)
        void inOrder(int index);// 中序遍历(左 → 根 → 右)→ 升序输出
        void postOrder(int index);// 后序遍历(左 → 右 → 根)

        //迭代遍历
        void preOrderIter(int index);// 前序遍历(根 → 左 → 右)
        void inOrderIter(int index);// 中序遍历(左 → 根 → 右)→ 升序输出
        void postOrderIter(int index);// 后序遍历(左 → 右 → 根)
        void levelOrderIter(int index);// 层序遍历(从上到下、从左到右)

        // 析构函数:自动销毁队列,避免内存泄漏
        ~ArrayBinaryTree() {
        }
};

四、建立二叉树实现详解

给定二叉树的中序和其他(前序、后序、层序)一种遍历的序列就可以确定一棵二叉树的结构。

4.1 前序建立二叉树(buildTreeByPre)

根据前序和中序序列建立二叉树


// 根据前序和中序列建立二叉树
// 参数:preTree-前序序列, preStart-前序起始索引, preEnd-前序结束索引
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByPre(const T preTree[], int preStart, int preEnd, 
    const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (preStart > preEnd || inStart > inEnd) {
        return;
    }

    qty = treeSize;//设置二叉树最大节点数

    T rootVal = preTree[preStart];      // 1. 当前根节点值(前序子序列第一个元素)
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数

    // 5. 递归构建左子树
    // 前序左子树范围:[preStart+1, preStart+leftSize],
    // 中序左子树范围:[inStart, rootIdx-1]
    // 左子节点编号:nodeNum * 2
    buildTreeByPre(preTree, preStart + 1, preStart + leftSize,
                       inTree, inStart, rootIdx - 1,
                       nodeNum * 2, treeSize);

    // 6. 递归构建右子树
    // 前序右子树范围:[preStart+leftSize+1, preEnd]
    // 中序右子树范围:[rootIdx+1, inEnd]
    // 右子节点编号:nodeNum * 2 + 1
    buildTreeByPre(preTree, preStart + leftSize + 1, preEnd,
                       inTree, rootIdx + 1, inEnd,
                       nodeNum * 2 + 1, treeSize);
}

4.2 后序建立二叉树(buildTreeByPost)

根据后序和中序列建立二叉树


// 根据后序和中序序列建立二叉树
// 参数:postTree-后序序列, postStart-后序起始索引, postEnd-后序结束索引
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByPost(const T postTree[], int postStart, int postEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (postStart > postEnd || inStart > inEnd) {
        return;
    }
    qty = treeSize;//设置二叉树最大节点数

    T rootVal = postTree[postEnd];      // 1. 后序序列最后一个元素是当前根节点
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数

    // 5. 递归构建左子树
    // 后序左子树范围:[postStart, postStart + leftSize - 1]
    // 中序左子树范围:[inStart, rootIdx - 1]
    // 左子节点编号:nodeNum * 2
    buildTreeByPost(postTree, postStart, postStart + leftSize - 1,
                      inTree, inStart, rootIdx - 1,
                      nodeNum * 2, treeSize);

    // 6. 递归构建右子树
    // 后序右子树范围:[postStart + leftSize, postEnd - 1]
    // 中序右子树范围:[rootIdx + 1, inEnd]
    // 右子节点编号:nodeNum * 2 + 1
    buildTreeByPost(postTree, postStart + leftSize, postEnd - 1,
                      inTree, rootIdx + 1, inEnd,
                      nodeNum * 2 + 1, treeSize);

}

4.3 层序建立二叉树(buildTreeByLevel)

根据层序和中序序列建立二叉树


// 根据层序和中序列建立二叉树
// 参数:levelTree-层序序列, levelLen-层序长度
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByLevel(const T levelTree[], int levelLen, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (inStart > inEnd || levelLen <= 0) {
        return;
    }
    qty = treeSize;//设置二叉树最大节点数

    T rootVal = levelTree[0];      // 1. 层序序列第一个元素是当前根节点
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数
    int rightSize = inEnd - rootIdx;    // 5. 计算右子树的节点个数

    // 6. 筛选层序数组中属于左、右子树的节点
    T leftLevel[MAXSIZE], rightLevel[MAXSIZE];
    int leftLevelLen = filterLevelNodes(levelTree, levelLen, inTree, inStart, rootIdx - 1, leftLevel);
    int rightLevelLen = filterLevelNodes(levelTree, levelLen, inTree, rootIdx + 1, inEnd, rightLevel);

    // 4. 递归构建左、右子树
    buildTreeByLevel(leftLevel, leftLevelLen, inTree, inStart, rootIdx - 1, nodeNum * 2, treeSize);
    buildTreeByLevel(rightLevel, rightLevelLen, inTree, rootIdx + 1, inEnd, nodeNum * 2 + 1, treeSize);

}

五、遍历实现详解

二叉树的遍历分为前序、中序、后序、层次。

5.1 递归前序遍历(preOrder)

从root节点开始,根 → 左 → 右的顺序遍历树,采用递归的方式实现,如果节点数比较大建议采用迭代方式实现,防止内存溢出。

template <typename T>
void ArrayBinaryTree<T>::preOrder(int index)
{
    if (index >qty) return;
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
    preOrder(index*2);
    preOrder(index*2+1);
}

5.2 递归中序遍历(inOrder)

从root节点开始,左 → 根 → 右的顺序遍历树,采用递归的方式实现,如果节点数比较大建议采用迭代方式实现,防止内存溢出。

template <typename T>
void ArrayBinaryTree<T>::inOrder(int index)
{
    if (index >qty) return;
    inOrder(index*2);
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
    inOrder(index*2+1);
}

5.3 递归后序遍历(postOrder)

从root节点开始,左 → 右 → 根的顺序遍历树,采用递归的方式实现,如果节点数比较大建议采用迭代方式实现,防止内存溢出。

template <typename T>
void ArrayBinaryTree<T>::postOrder(int index)
{
    if (index >qty) return;
    postOrder(index*2);
    postOrder(index*2+1);
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
}

5.4 迭代前序遍历(迭代)

二叉树的遍历分为前序、中序、后序、层次。

4.3.1 前序遍历(preOrderIter)

从root节点开始,根 → 左 → 右的顺序遍历树,采用迭代+栈的方式实现,如果节点数比较小建议采用递归方式实现(容易实现)。

template <typename T>
void ArrayBinaryTree<T>::preOrderIter(int index)
{
    std::stack<int> stack1;  // 存储节点编号
    stack1.push(index);        // 根节点入栈

    while (stack1.size() >= 1) {
        int currIndex = stack1.top();stack1.pop();  // 出栈
        if (currIndex >= qty) {
            continue;
        }
        if(tree[currIndex] != valNull)
            std::cout<<tree[currIndex]<<" ";  // 访问根

        // 栈后进先出,先入栈右子树,后入栈左子树
        int rightIndex = currIndex * 2 + 1;
        if (rightIndex <= qty) {
            stack1.push(rightIndex);
        }
        int leftIndex = currIndex * 2;
        if (leftIndex <= qty) {
            stack1.push(leftIndex);
        }
    }
}

5.5 迭代中序遍历(inOrderIter)

从root节点开始,左 → 根 → 右的顺序遍历树,采用迭代+栈的方式实现,如果节点数比较小建议采用递归方式实现(容易实现)。

template <typename T>
void ArrayBinaryTree<T>::inOrderIter(int index)
{
    std::stack<int> stack1;  // 存储节点编号
    int currIndex = index;
    T valNull = T();

    // 迭代终止条件:当前节点为空 且 栈为空
    while (stack1.size()>=1 || (currIndex < qty && tree[currIndex] != valNull)) {
        // 第一步:遍历到最左子节点,路径上的节点索引入栈
        while( currIndex <= qty && tree[currIndex] != valNull ) {
            stack1.push(currIndex);
            currIndex = currIndex * 2;  // 左子节点
        }

        // 第二步:弹出栈顶节点(最左节点)
        currIndex = stack1.top();stack1.pop();
        std::cout<<tree[currIndex]<<" ";

        // 第三步:转向右子节点
        currIndex = currIndex * 2 + 1;
    }
}

5.6 迭代后序遍历(postOrderIter)

从root节点开始,左 → 右 → 根的顺序遍历树,采用迭代+栈的方式实现,如果节点数比较小建议采用递归方式实现(容易实现)。

template <typename T>
void ArrayBinaryTree<T>::postOrderIter(int index)
{
    std::stack<int> stack1, stack2;
    stack1.push(index);

    // 栈1:根→右→左;栈2:存储逆序结果
    while (stack1.size() >= 1) {
        int currIndex = stack1.top(); stack1.pop();
        if (currIndex > qty) {
            continue;
        }
        stack2.push(currIndex);

        // 先入栈左子树,后入栈右子树(栈1出栈顺序相反)
        int leftIndex = currIndex * 2;
        if (leftIndex <= qty) {
            stack1.push(leftIndex);
        }
        int rightIndex = currIndex * 2 + 1;
        if (rightIndex <= qty) {
            stack1.push(rightIndex);
        }
    }

    // 输出栈2(后序遍历结果)
    while(stack2.size() >= 1) {
        int currIndex = stack2.top(); stack2.pop();
        if(tree[currIndex] != valNull)
            std::cout<<tree[currIndex]<<" ";
    }
}

5.7 迭代层序遍历(levelOrderIter)

从rode节点开始,从上到下、从左到右顺序遍历树。采用迭代+队列的方式实现。

template <typename T>
void ArrayBinaryTree<T>::levelOrderIter(int index)
{
    if (index <= 0) return;

    std::queue queues;
    queues.push(index); // 根节点入队

    while (!queues.empty()) {
        int curr = queues.front(); // 获取队头节点
        queues.pop();// 出队头节点
        if(tree[curr] != valNull)
            std::cout<<tree[curr]<<" "; // 输出当前节点值

        // 左子节点入队(先左后右)
        if (curr <= qty) {
            queues.push(curr*2);
        }
        // 右子节点入队
        if (curr <= qty) {
            queues.push(curr*2+1);
        }
    }
}

说、实战使用示例

6.1 基础类型(char)使用示例

#include "ArrayBinaryTree.h"
#include <iostream>

int main() {
    ArrayBinaryTree<char> tree1;
    ArrayBinaryTree<char> tree2;
    ArrayBinaryTree<char> tree3;

    // 1. 根据前序和中序建立二叉树
    printf("== 1.建立二叉树(根据前序和中序) ==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("       / \\ / \\ \n");
    printf("      D  E F    \n");
    printf("        / /    \n");
    printf("       G H    \n");
    char preTree1[] = {'A', 'B', 'D', 'E', 'G', 'C', 'F', 'H'};// 前序序列
    char inTree1[] =  {'D', 'B', 'G', 'E', 'A', 'C', 'H', 'F'};// 中序序列
    int n1 = sizeof(preTree1) / sizeof(preTree1[0]); // 计算元素个数
    int k1 = floor(log2(n1)) + 1;// 计算二叉树深度
    int treeSize1 = pow(2, k1) - 1;// 计算二叉树最大节点数
    tree1.buildTreeByPre(preTree1, 0, n1-1, inTree1, 0, n1-1, 1, treeSize1); //建立二叉树
    printf("\n===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree1.preOrder(1); printf("\n");
    printf("中序遍历:"); tree1.inOrder(1); printf("\n");
    printf("后序遍历:"); tree1.postOrder(1); printf("\n");
    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree1.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree1.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree1.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree1.levelOrderIter(1); printf("\n");

    // 2. 根据后序和中序建立二叉树
    printf("\n== 2.建立二叉树(根据后序和中序)==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("         \\ / \\ \n");
    printf("         D E  F\n");
    printf("          \\   / \n");
    printf("           G  H \n");
    char postTree2[] = {'G', 'D', 'B', 'E', 'H', 'F', 'C', 'A'};// 后序序列
    char inTree2[] =   {'D', 'G', 'B', 'A', 'E', 'C', 'H', 'F'};// 中序序列

    int n2 = sizeof(postTree2) / sizeof(postTree2[0]); // 计算元素个数
    int k2 = floor(log2(n2)) + 1;// 计算二叉树深度
    int treeSize2 = pow(2, k2) - 1;// 计算二叉树最大节点数
    tree2.buildTreeByPost(postTree2, 0, n2-1, inTree2, 0, n2-1, 1, treeSize2);//建立二叉树
    printf("===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree2.preOrder(1); printf("\n");
    printf("中序遍历:"); tree2.inOrder(1); printf("\n");
    printf("后序遍历:"); tree2.postOrder(1); printf("\n");
    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree2.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree2.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree2.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree2.levelOrderIter(1); printf("\n");

    // 3. 根据层序和中序建立二叉树
    printf("\n== 3.建立二叉树(根据层序和中序)==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("         \\ / \\ \n");
    printf("         D E  F\n");
    printf("          \\   / \n");
    printf("           G  H \n");
    char levelTree3[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};// 层序序列
    char inTree3[] =   {'D', 'G', 'B', 'A', 'E', 'C', 'H', 'F'};// 中序序列

    int n3 = sizeof(levelTree3) / sizeof(levelTree3[0]); // 计算元素个数
    int k3 = floor(log2(n3)) + 1;// 计算二叉树深度
    int treeSize3 = pow(2, k3) - 1;// 计算二叉树最大节点数
    tree3.buildTreeByLevel(levelTree3, n3, inTree3, 0, n3-1, 1, treeSize3);//建立二叉树
    printf("===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree3.preOrder(1); printf("\n");
    printf("中序遍历:"); tree3.inOrder(1); printf("\n");
    printf("后序遍历:"); tree3.postOrder(1); printf("\n");

    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree3.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree3.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree3.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree3.levelOrderIter(1); printf("\n");

    return 0;
}

6.2 运行结果


== 1.建立二叉树(根据前序和中序) ==
          A
         / \
        B   C
       / \ / \
      D  E F
        / /
       G H

===== 递归遍历测试 =====
前序遍历:A B D E G C F H
中序遍历:D B G E A C H F
后序遍历:D G E B H F C A
===== 迭代遍历测试 =====
前序遍历:A B D E G C F H
中序遍历:D B G E A C H F
后序遍历:D G E B H F C A
层序遍历:A B C D E F G H

== 2.建立二叉树(根据后序和中序)==
          A
         / \
        B   C
         \ / \
         D E  F
          \   /
           G  H
===== 递归遍历测试 =====
前序遍历:A B D G C E F H
中序遍历:D G B A E C H F
后序遍历:G D B E H F C A
===== 迭代遍历测试 =====
前序遍历:A B D G C E F H
中序遍历:D G B A E C H F
后序遍历:G D B E H F C A
层序遍历:A B C D E F G H

== 3.建立二叉树(根据层序和中序)==
          A
         / \
        B   C
         \ / \
         D E  F
          \   /
           G  H
===== 递归遍历测试 =====
前序遍历:A B D G C E F H
中序遍历:D G B A E C H F
后序遍历:G D B E H F C A
===== 迭代遍历测试 =====
前序遍历:A B D G C E F H
中序遍历:D G B A E C H F
后序遍历:G D B E H F C A
层序遍历:A B C D E F G H
            

七、完整可运行代码

7.1 ArrayBinaryTree.h 头文件


#ifndef ARRAYBINARYTREE_H_INCLUDED
#define ARRAYBINARYTREE_H_INCLUDED

#include<queue>
#include<stack>

//************************************************************************************************************************************************************************
//
//      类名:数组二叉树(ArrayBinaryTree)
//
//      概述:一个可复用的数组二叉树,存储结构采用数组实现,支持任意类型数据(模板泛型)。
//
//      说明:默认二叉树的最大容量为100
//
//************************************************************************************************************************************************************************

#define MAXSIZE 100  // 二叉树的最大容量


//========================================================================================================================================================================
//
//                                                                 数组二叉树结构体(ArrayBinaryTree)
//
//========================================================================================================================================================================
template <typename T>
struct ArrayBinaryTree{
    // ------------------------------------------------------------------------------------------------------
    //                                          私有成员
    // 注:私有成员只能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)不能访问调用)
    //------------------------------------------------------------------------------------------------------
    private:

        //---------------声明私有成员变量---------------

        T tree[MAXSIZE];   // 存储二叉树数据,支持任意类型
        int qty;         // 用于跟踪二叉树中的元素数量
        T valNull = T(); // 空节点标识(模板化)

        //---------------声明私有成员函数---------------

        //辅助函数
        int findRootIndex(const T inTree[], int start, int end, const T rootVal); // 查找根节点在中序序列中的索引
        int isInRange(const T val, const T inOrder[], int start, int end); // 检查元素是否在中序的指定范围内(用于筛选层序中的子树节点)
        int filterLevelNodes(const T levelOrder[], int levelLen, const T inOrder[], int inStart, int inEnd, T subLevel[]);// 筛选层序数组中属于指定中序范围的节点,生成子层序数组

    // ------------------------------------------------------------------------------------------------------
    //                                          公共成员
    // 注:公共成员能在该结构体内部访问调用,外部通过该结构体定义(实例化)的变量(对象)也能访问调用)
    //------------------------------------------------------------------------------------------------------
    public:

        //---------------声明公共成员函数---------------

        // 构造函数:外部通过该结构体定义(实例化)变量(对象)时,自动执行该函数(主要用于初始化成员变量的值)
        ArrayBinaryTree() {
            qty = 0;
            for(int i=0;i < MAXSIZE;i++) { tree[i] = T(); }
        }

        //功能函数
        void buildTreeByPre(const T preTree[], int preStart, int preEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据前序和中序列建立二叉树
        void buildTreeByPost(const T postTree[], int postStart, int postEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据后序和中序列建立二叉树
        void buildTreeByLevel(const T levelTree[], int levelLen, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize);// 根据层序和中序列建立二叉树
        void deleteTree(int index);// 删除二叉树

        //递归遍历
        void preOrder(int index);// 前序遍历(根 → 左 → 右)
        void inOrder(int index);// 中序遍历(左 → 根 → 右)→ 升序输出
        void postOrder(int index);// 后序遍历(左 → 右 → 根)

        //迭代遍历
        void preOrderIter(int index);// 前序遍历(根 → 左 → 右)
        void inOrderIter(int index);// 中序遍历(左 → 根 → 右)→ 升序输出
        void postOrderIter(int index);// 后序遍历(左 → 右 → 根)
        void levelOrderIter(int index);// 层序遍历(从上到下、从左到右)

        // 析构函数:自动销毁队列,避免内存泄漏
        ~ArrayBinaryTree() {
        }
};

#endif // ARRAYBINARYTREE_H_INCLUDED
                

7.2 ArrayBinaryTree.cpp 程序代码


#include <iostream>
#include "ArrayBinaryTree.h"

//---------------实现私有成员函数---------------


// 查找根节点在中序序列中的索引
template <typename T>
int ArrayBinaryTree<T>::findRootIndex(const T inTree[], int start, int end, const T rootVal) {
    for (int i = start; i <= end; i++) {
        if (inTree[i] == rootVal) {
            return i;
        }
    }
    return -1;  // 未找到(理论上不会出现)
}

// 检查元素是否在中序的指定范围内(用于筛选层序中的子树节点)
template <typename T>
int ArrayBinaryTree<T>::isInRange(const T val, const T inOrder[], int start, int end) {
    for (int i = start; i <= end; i++) {
        if (inOrder[i] == val) {
            return 1;
        }
    }
    return 0;
}

// 筛选层序数组中属于指定中序范围的节点,生成子层序数组
template <typename T>
int ArrayBinaryTree<T>::filterLevelNodes(const T levelOrder[], int levelLen, const T inOrder[], int inStart, int inEnd, T subLevel[]) {
    int idx = 0;
    for (int i = 0; i < levelLen; i++) {
        if (isInRange(levelOrder[i], inOrder, inStart, inEnd)) {
            subLevel[idx++] = levelOrder[i];
        }
    }
    return idx;  // 返回子层序数组的长度
}

//---------------实现公共成员函数---------------

// 根据前序和中序列建立二叉树
// 参数:preTree-前序序列, preStart-前序起始索引, preEnd-前序结束索引
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByPre(const T preTree[], int preStart, int preEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (preStart > preEnd || inStart > inEnd) {
        return;
    }

    qty = treeSize;//设置二叉树最大节点数

    T rootVal = preTree[preStart];      // 1. 当前根节点值(前序子序列第一个元素)
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数

    // 5. 递归构建左子树
    // 前序左子树范围:[preStart+1, preStart+leftSize],
    // 中序左子树范围:[inStart, rootIdx-1]
    // 左子节点编号:nodeNum * 2
    buildTreeByPre(preTree, preStart + 1, preStart + leftSize,
                       inTree, inStart, rootIdx - 1,
                       nodeNum * 2, treeSize);

    // 6. 递归构建右子树
    // 前序右子树范围:[preStart+leftSize+1, preEnd]
    // 中序右子树范围:[rootIdx+1, inEnd]
    // 右子节点编号:nodeNum * 2 + 1
    buildTreeByPre(preTree, preStart + leftSize + 1, preEnd,
                       inTree, rootIdx + 1, inEnd,
                       nodeNum * 2 + 1, treeSize);
}

// 根据后序和中序列建立二叉树
// 参数:postTree-后序序列, postStart-后序起始索引, postEnd-后序结束索引
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByPost(const T postTree[], int postStart, int postEnd, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (postStart > postEnd || inStart > inEnd) {
        return;
    }
    qty = treeSize;//设置二叉树最大节点数

    T rootVal = postTree[postEnd];      // 1. 后序序列最后一个元素是当前根节点
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数

    // 5. 递归构建左子树
    // 后序左子树范围:[postStart, postStart + leftSize - 1]
    // 中序左子树范围:[inStart, rootIdx - 1]
    // 左子节点编号:nodeNum * 2
    buildTreeByPost(postTree, postStart, postStart + leftSize - 1,
                      inTree, inStart, rootIdx - 1,
                      nodeNum * 2, treeSize);

    // 6. 递归构建右子树
    // 后序右子树范围:[postStart + leftSize, postEnd - 1]
    // 中序右子树范围:[rootIdx + 1, inEnd]
    // 右子节点编号:nodeNum * 2 + 1
    buildTreeByPost(postTree, postStart + leftSize, postEnd - 1,
                      inTree, rootIdx + 1, inEnd,
                      nodeNum * 2 + 1, treeSize);

}

// 根据层序和中序列建立二叉树
// 参数:levelTree-层序序列, levelLen-层序长度
//       inTree-中序序列, inStart-中序起始索引,inEnd-中序结束索引
//       nodeNum-当前节点的编号(从1开始)
template <typename T>
void ArrayBinaryTree<T>::buildTreeByLevel(const T levelTree[], int levelLen, const T inTree[], int inStart, int inEnd, int nodeNum, int treeSize) {
    if (inStart > inEnd || levelLen <= 0) {
        return;
    }
    qty = treeSize;//设置二叉树最大节点数

    T rootVal = levelTree[0];      // 1. 层序序列第一个元素是当前根节点
    tree[nodeNum] = rootVal;            // 2. 将根节点存入数组对应位置
    int rootIdx = findRootIndex(inTree, inStart, inEnd, rootVal);// 3. 找到根节点在中序序列中的索引
    int leftSize = rootIdx - inStart;   // 4. 计算左子树的节点个数
    int rightSize = inEnd - rootIdx;    // 5. 计算右子树的节点个数

    // 6. 筛选层序数组中属于左、右子树的节点
    T leftLevel[MAXSIZE], rightLevel[MAXSIZE];
    int leftLevelLen = filterLevelNodes(levelTree, levelLen, inTree, inStart, rootIdx - 1, leftLevel);
    int rightLevelLen = filterLevelNodes(levelTree, levelLen, inTree, rootIdx + 1, inEnd, rightLevel);

    // 4. 递归构建左、右子树
    buildTreeByLevel(leftLevel, leftLevelLen, inTree, inStart, rootIdx - 1, nodeNum * 2, treeSize);
    buildTreeByLevel(rightLevel, rightLevelLen, inTree, rootIdx + 1, inEnd, nodeNum * 2 + 1, treeSize);

}

// 删除二叉树
template <typename T>
void ArrayBinaryTree<T>::deleteTree(int index)
{
    if (index>qty) return;
    tree[index] = T();
    deleteTree(index*2);
    deleteTree(index*2+1);
}

// 前序遍历(根 → 左 → 右)
template <typename T>
void ArrayBinaryTree<T>::preOrder(int index)
{
    if (index >qty) return;
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
    preOrder(index*2);
    preOrder(index*2+1);
}

// 中序遍历(左 → 根 → 右)
template <typename T>
void ArrayBinaryTree<T>::inOrder(int index)
{
    if (index >qty) return;
    inOrder(index*2);
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
    inOrder(index*2+1);
}

// 后序遍历(左 → 右 → 根)
template <typename T>
void ArrayBinaryTree<T>::postOrder(int index)
{
    if (index >qty) return;
    postOrder(index*2);
    postOrder(index*2+1);
    if(tree[index] != valNull)
        std::cout<<tree[index]<<" ";
}

// 迭代---前序遍历(根 → 左 → 右)
template <typename T>
void ArrayBinaryTree<T>::preOrderIter(int index)
{
    std::stack<int> stack1;  // 存储节点编号
    stack1.push(index);        // 根节点入栈

    while (stack1.size() >= 1) {
        int currIndex = stack1.top();stack1.pop();  // 出栈
        if (currIndex >= qty) {
            continue;
        }
        if(tree[currIndex] != valNull)
            std::cout<<tree[currIndex]<<" ";  // 访问根

        // 栈后进先出,先入栈右子树,后入栈左子树
        int rightIndex = currIndex * 2 + 1;
        if (rightIndex <= qty) {
            stack1.push(rightIndex);
        }
        int leftIndex = currIndex * 2;
        if (leftIndex <= qty) {
            stack1.push(leftIndex);
        }
    }
}

// 迭代---中序遍历(左 → 根 → 右)
template <typename T>
void ArrayBinaryTree<T>::inOrderIter(int index)
{
    std::stack<int> stack1;  // 存储节点编号
    int currIndex = index;
    T valNull = T();

    // 迭代终止条件:当前节点为空 且 栈为空
    while (stack1.size()>=1 || (currIndex < qty && tree[currIndex] != valNull)) {
        // 第一步:遍历到最左子节点,路径上的节点下标入栈
        while( currIndex <= qty && tree[currIndex] != valNull ) {
            stack1.push(currIndex);
            currIndex = currIndex * 2;  // 左子节点
        }

        // 第二步:弹出栈顶节点(最左节点)
        currIndex = stack1.top();stack1.pop();
        std::cout<<tree[currIndex]<<" ";

        // 第三步:转向右子节点
        currIndex = currIndex * 2 + 1;
    }
}

// 迭代---后序遍历(左 → 右 → 根)
template <typename T>
void ArrayBinaryTree<T>::postOrderIter(int index)
{
    std::stack<int> stack1, stack2;
    stack1.push(index);

    // 栈1:根→右→左;栈2:存储逆序结果
    while (stack1.size() >= 1) {
        int currIndex = stack1.top(); stack1.pop();
        if (currIndex > qty) {
            continue;
        }
        stack2.push(currIndex);

        // 先入栈左子树,后入栈右子树(栈1出栈顺序相反)
        int leftIndex = currIndex * 2;
        if (leftIndex <= qty) {
            stack1.push(leftIndex);
        }
        int rightIndex = currIndex * 2 + 1;
        if (rightIndex <= qty) {
            stack1.push(rightIndex);
        }
    }

    // 输出栈2(后序遍历结果)
    while(stack2.size() >= 1) {
        int currIndex = stack2.top(); stack2.pop();
        if(tree[currIndex] != valNull)
            std::cout<<tree[currIndex]<<" ";
    }
}

// 迭代---层序遍历(根 → 左 → 右)
template <typename T>
void ArrayBinaryTree<T>::levelOrderIter(int index)
{
    if (index <= 0) return;

    std::queue<int> queues;
    queues.push(index); // 根节点入队

    while (!queues.empty()) {
        int curr = queues.front(); // 获取队头节点
        queues.pop();// 出队头节点
        if(tree[curr] != valNull)
            std::cout<<tree[curr]<<" "; // 输出当前节点值

        // 左子节点入队(先左后右)
        if (curr <= qty) {
            queues.push(curr*2);
        }
        // 右子节点入队
        if (curr <= qty) {
            queues.push(curr*2+1);
        }
    }
}

// 显式实例化常用类型(避免链接错误,可选)
template class ArrayBinaryTree<int>;
template class ArrayBinaryTree<float>;
template class ArrayBinaryTree<std::string>;

7.3 main.cpp 测试代码

#include "ArrayBinaryTree.h"
#include <iostream>
#include <string>

int main() {
    ArrayBinaryTree<char> tree1;
    ArrayBinaryTree<char> tree2;
    ArrayBinaryTree<char> tree3;

    // 1. 根据前序和中序建立二叉树
    printf("== 1.建立二叉树(根据前序和中序) ==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("       / \\ / \\ \n");
    printf("      D  E F    \n");
    printf("        / /    \n");
    printf("       G H    \n");
    char preTree1[] = {'A', 'B', 'D', 'E', 'G', 'C', 'F', 'H'};// 前序序列
    char inTree1[] =  {'D', 'B', 'G', 'E', 'A', 'C', 'H', 'F'};// 中序序列
    int n1 = sizeof(preTree1) / sizeof(preTree1[0]); // 计算元素个数
    int k1 = floor(log2(n1)) + 1;// 计算二叉树深度
    int treeSize1 = pow(2, k1) - 1;// 计算二叉树最大节点数
    tree1.buildTreeByPre(preTree1, 0, n1-1, inTree1, 0, n1-1, 1, treeSize1); //建立二叉树
    printf("\n===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree1.preOrder(1); printf("\n");
    printf("中序遍历:"); tree1.inOrder(1); printf("\n");
    printf("后序遍历:"); tree1.postOrder(1); printf("\n");
    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree1.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree1.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree1.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree1.levelOrderIter(1); printf("\n");

    // 2. 根据后序和中序建立二叉树
    printf("\n== 2.建立二叉树(根据后序和中序)==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("         \\ / \\ \n");
    printf("         D E  F\n");
    printf("          \\   / \n");
    printf("           G  H \n");
    char postTree2[] = {'G', 'D', 'B', 'E', 'H', 'F', 'C', 'A'};// 后序序列
    char inTree2[] =   {'D', 'G', 'B', 'A', 'E', 'C', 'H', 'F'};// 中序序列
    int n2 = sizeof(postTree2) / sizeof(postTree2[0]); // 计算元素个数
    int k2 = floor(log2(n2)) + 1;// 计算二叉树深度
    int treeSize2 = pow(2, k2) - 1;// 计算二叉树最大节点数
    tree2.buildTreeByPost(postTree2, 0, n2-1, inTree2, 0, n2-1, 1, treeSize2);//建立二叉树
    printf("===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree2.preOrder(1); printf("\n");
    printf("中序遍历:"); tree2.inOrder(1); printf("\n");
    printf("后序遍历:"); tree2.postOrder(1); printf("\n");
    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree2.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree2.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree2.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree2.levelOrderIter(1); printf("\n");

    // 3. 根据层序和中序建立二叉树
    printf("\n== 3.建立二叉树(根据层序和中序)==\n");
    printf("          A \n");
    printf("         / \\ \n");
    printf("        B   C \n");
    printf("         \\ / \\ \n");
    printf("         D E  F\n");
    printf("          \\   / \n");
    printf("           G  H \n");
    char levelTree3[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};// 层序序列
    char inTree3[] =   {'D', 'G', 'B', 'A', 'E', 'C', 'H', 'F'};// 中序序列
    int n3 = sizeof(levelTree3) / sizeof(levelTree3[0]); // 计算元素个数
    int k3 = floor(log2(n3)) + 1;// 计算二叉树深度
    int treeSize3 = pow(2, k3) - 1;// 计算二叉树最大节点数
    tree3.buildTreeByLevel(levelTree3, n3, inTree3, 0, n3-1, 1, treeSize3);//建立二叉树
    printf("===== 递归遍历测试 =====\n");
    printf("前序遍历:"); tree3.preOrder(1); printf("\n");
    printf("中序遍历:"); tree3.inOrder(1); printf("\n");
    printf("后序遍历:"); tree3.postOrder(1); printf("\n");
    printf("===== 迭代遍历测试 =====\n");
    printf("前序遍历:"); tree3.preOrderIter(1); printf("\n");
    printf("中序遍历:"); tree3.inOrderIter(1); printf("\n");
    printf("后序遍历:"); tree3.postOrderIter(1); printf("\n");
    printf("层序遍历:"); tree3.levelOrderIter(1); printf("\n");
    
    return 0;
}

八、注意事项

模板类型约束

  • 模板类型需支持</>/==运算符(内置类型如int/string默认支持,自定义类型需重载);
  • 自定义类型需重载<<运算符(遍历输出时使用)。

九、总结

通过理论学习+代码实践,就能真正掌握树与二叉树的核心逻辑,为后续学习更复杂的数据结构打下坚实基础!


返回顶部